// 这是一个封装websocket服务的通用接口
import { Observable } from 'rxjs'
import { message, Modal } from 'ant-design-vue'
export class requestWs {
  // scoket连接地址
  //   wsUrl = 'ws://127.0.0.1:8888/ocr-server/server/3'
  wsUrl = 'ws://192.168.3.32:8000'

  // socket对象
  socket = null

  // 创建一个rx事物map对象
  //   key :{
  //     method: ApiMethod;
  //     args: ;
  //     observer: Subscriber<unknown>;
  //   }
  pendingCalls = new Map()

  // message loading key
  loadingKey = 'socketReconnect'

  // 多少秒重新连接
  timeout = 1

  // 尝试连接次数
  reconnectAttempts = 0
  // 最大尝试次数
  maxReconnectAttempts = 5
  // 锁定连接
  lockReconnect = false
  // 连接成功
  connected = false

  // 消息对象
  ApiEventMessage = {
    Connect: 'connect',
    Method: 'method'
  }

  constructor() {
    this.connect()
  }

  // 外部调用关闭
  close = () => {
    this.socket.close()
  }

  // 外部调用此函数链式调用
  call = (target, op, params = {}, type = 'str') => {
    let uuid = 'requestWs-' + new Date().getTime() + '-' + Math.random()
    const payload = {
      id: uuid,
      msg: this.ApiEventMessage.Method,
      target,
      op,
      params
    }
    // 创建一个新事件 rxjs
    return new Observable((observer) => {
      console.log('执行....')
      // 存储调用事物对象用于后续的接收消息时候使用
      this.pendingCalls.set(uuid, {
        target,
        op,
        params,
        observer
      })

      // 接口调用消息发送
      this.send(payload, type)
    })
  }

  // 重新连接
  reconnect = () => {
    if (this.lockReconnect) return
    this.lockReconnect = true
    setTimeout(() => {
      this.reconnectAttempts++
      message.loading({ content: '正在重新连接...' + this.reconnectAttempts + '次', key: this.loadingKey, duration: 0 })
      if (this.reconnectAttempts <= this.maxReconnectAttempts) {
        // 重新连接
        console.log('建立连接 - 重新连接' + this.reconnectAttempts + '次')
        this.connect()
        setTimeout(() => {
          this.socket.close()
        }, this.timeout * 1000)
      } else {
        message.error({ content: '连接失败,检查网络是否正常', key: this.loadingKey })
        this.reconnectAttempts = 0
      }
      this.lockReconnect = false
    }, this.timeout * 1000)
  }

  // 创建连接初始化
  connect = () => {
    console.log('建立连接...')
    // 定义socket连接
    this.socket = new WebSocket(this.wsUrl)

    // 建立连接成功调用函数
    this.socket.onopen = this.onOpen.bind(this)
    // 建立联机错误调用函数
    this.socket.onerror = this.onError.bind(this)
    // 接收消息调用函数
    this.socket.onmessage = this.onMessage.bind(this)
    // 连接关闭调用函数
    this.onclose = this.onClose.bind(this)
  }

  //连接异常回调
  onError(e) {
    console.log('建立连接 - 错误')
    this.reconnect() //重连
  }

  // 建立连接成功函数
  onOpen = () => {
    console.log('建立连接 - 成功')
  }

  // 接收消息函数
  onMessage = (msg) => {
    console.log('建立连接 - 消息接收成功', msg)
    let data = JSON.parse(msg.data)

    const call = this.pendingCalls.get(data.id)
    this.pendingCalls.delete(data.id)
    if (call && call.observer) {
      let result = data.result
      // 状态错误
      if (data.state == 1) {
        let errormsg = result.message ? result.message : '系统异常，请稍后再试'
        message.error(errormsg)
      } else {
        call.observer.next(result)
      }
      call.observer.complete()
    }
  }

  // 连接关闭调用函数
  onClose = () => {
    console.log('建立连接 - 关闭')
    this.pendingCalls = new Map()
  }

  // 发送消息推送
  send = (payload, type) => {
    if (this.socket.readyState == WebSocket.OPEN) {
      if (!this.connected) {
        message.success({ content: '连接成功', key: this.loadingKey })
        this.connected = true
      }
      if (type == 'str') {
        // 连接成功
        this.socket.send(JSON.stringify(payload))
      } else if (type == 'obj') {
        this.socket.send(payload)
      }

      console.log('建立连接 - 消息推送成功', payload)
    } else {
      console.error('建立连接 - 消息推送失败', payload)
      // 重新连接
      this.reconnect()
    }
  }
}

export default requestWs
